package com.lambkit.module.upms.auth.service;

import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.StrUtil;
import com.lambkit.auth.AuthUser;
import com.lambkit.auth.exception.IncorrectCredentialsException;
import com.lambkit.auth.exception.LockedAccountException;
import com.lambkit.auth.exception.UnknownAccountException;
import com.lambkit.auth.service.AuthHttpService;
import com.lambkit.auth.service.AuthKernelService;
import com.lambkit.auth.service.AuthSessionService;
import com.lambkit.core.Attr;
import com.lambkit.core.Lambkit;
import com.lambkit.core.LambkitResult;
import com.lambkit.core.http.IRequest;
import com.lambkit.db.sql.Example;
import com.lambkit.module.upms.Upms;
import com.lambkit.module.upms.UpmsApiService;
import com.lambkit.module.upms.UpmsConfig;
import com.lambkit.module.upms.UpmsLoginUserToken;
import com.lambkit.module.upms.encrypt.RSAKeyRender;
import com.lambkit.module.upms.row.UpmsUser;
import com.lambkit.module.upms.row.UpmsUserOrganization;
import com.lambkit.module.upms.row.UpmsUserRole;
import com.lambkit.module.upms.service.UpmsLogService;
import com.lambkit.module.upms.service.UpmsSystemService;
import com.lambkit.module.upms.service.UpmsUserOrganizationService;
import com.lambkit.module.upms.service.UpmsUserRoleService;
import com.lambkit.module.upms.sql.UpmsSystemSQL;
import com.lambkit.module.upms.sql.UpmsUserOrganizationSQL;
import com.lambkit.module.upms.sql.UpmsUserRoleSQL;
import com.lambkit.web.AjaxResult;
import com.lambkit.web.ResultConsts;
import com.lambkit.web.captcha.HutoolShearCaptcha;

import java.util.List;

/**
 * @author yangyong(孤竹行)
 */
public class UpmsHttpService implements AuthHttpService {

    private UpmsDataService dataService;

    public UpmsHttpService() {
        dataService = Lambkit.get(UpmsDataService.class);
    }

    private UpmsApiService getUpmsApiService() {
        UpmsApiService upmsApiService = Lambkit.get(UpmsApiService.class);
        return upmsApiService;
    }

    private AuthKernelService getLoginService(IRequest request) {
        return Upms.use(request).getAuthKernelService();
    }

    @Override
    public String getSessionIdOrToken(IRequest request) {
//        AuthConfig authConfig = Lambkit.config(AuthConfig.class);
//        return request.getHeader(authConfig.getHeader());
        AuthSessionService sessionService = Lambkit.get(AuthSessionService.class, UpmsSessionService.class);
        return sessionService.getId(request);
    }

    @Override
    public AuthUser getAuth(IRequest request) {
        return getLoginService(request).getAuth(getSessionIdOrToken(request));
    }

    @Override
    public String authenticate(IRequest request) {
        return getLoginService(request).authenticate(getSessionIdOrToken(request));
    }

    @Override
    public LambkitResult login(IRequest request) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String sessionId = getSessionIdOrToken(request);
        UpmsConfig upmsConfig = Lambkit.config(UpmsConfig.class);
        if(dataService.getCache().getLoginError(sessionId) > upmsConfig.getAccountLockerNum()) {
            LambkitResult result = AjaxResult.by(ResultConsts.INVALID_ACCOUNT).message("设备已锁定！");
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }
        if(dataService.getCache().getLoginError(username) > upmsConfig.getAccountLockerNum()) {
            LambkitResult result = AjaxResult.by(ResultConsts.INVALID_ACCOUNT).message("帐号已锁定！");
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }
        if (StrUtil.isBlank(username)) {
            LambkitResult result = AjaxResult.by(ResultConsts.EMPTY_USERNAME).message("帐号不能为空！");
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }

        //int accountType = 0;
        int loginType = 0;
        // 查询用户信息
        UpmsUser upmsUser = null;
        if(Validator.isMobile(username)) {
            //accountType = 1;
            loginType = 1;
            upmsUser = getUpmsApiService().selectUpmsUserByPhone(username);
        } else if(Validator.isEmail(username)) {
            //accountType = 2;
            upmsUser = getUpmsApiService().selectUpmsUserByEmail(username);
        } else {
            // 查询用户信息
            upmsUser = getUpmsApiService().selectUpmsUserByLoginName(username);
        }
        if (null == upmsUser) {
            Integer error = dataService.getCache().addLoginError(sessionId);
            LambkitResult result = AjaxResult.by(ResultConsts.INVALID_USERNAME).message("帐号或密码错误！错误6次后锁定!");//帐号不存在！错误" + error + "次，错误6次后锁定
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }

        String typeStr = request.getParameter("type");
        if("account".equalsIgnoreCase(typeStr)) {
            loginType = 0;
        } else if("sms".equalsIgnoreCase(typeStr)) {
            loginType = 1;
        }
        //确定了loginType
        UpmsLoginUserToken userToken = new UpmsLoginUserToken(username, password, loginType);
        LambkitResult result = loginValidate(request, userToken, sessionId);
        if(result!=null && result.getCode()!=ResultConsts.SUCCESS.getCode()) {
            return result;
        }
        AuthUser authUser = dataService.getAuthUser(upmsUser);
        String sessionIdOrtoken;
        try {
            sessionIdOrtoken = getLoginService(request).login(authUser, password, loginType);
        } catch (UnknownAccountException e) {
            Integer error = dataService.getCache().addLoginError(sessionId);
            result = AjaxResult.by(ResultConsts.INVALID_USERNAME).message("帐号或密码错误！错误6次后锁定!");//错误" + error + "次，
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        } catch (IncorrectCredentialsException e) {
            Integer error = dataService.getCache().addLoginError(username);
            if(userToken.getLoginType()==1) {
                result = AjaxResult.by(ResultConsts.INVALID_CAPTCHA).message("验证码错误！错误6次后锁定!");//错误" + error + "次，
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            } else {
                result = AjaxResult.by(ResultConsts.INVALID_PASSWORD).message("帐号或密码错误！错误6次后锁定!");//错误" + error + "次，
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            }
        } catch (LockedAccountException e) {
            result = AjaxResult.by(ResultConsts.INVALID_ACCOUNT).message("帐号已锁定！");
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }

        String type = request.getParameter("type");
        if(StrUtil.isNotBlank(type) && "info".equals(type) && getUpmsApiService()!=null) {
            Attr data = Attr.by("user", upmsUser);
            // 用户拥有组织
            Example upmsUserOrganizationExample = UpmsUserOrganizationSQL.of().andUserIdEqualTo(upmsUser.getUserId()).example();
            List<UpmsUserOrganization> upmsUserOrganizations = Lambkit.get(UpmsUserOrganizationService.class).dao().find(upmsUserOrganizationExample);
            data.set("userOrganizations", upmsUserOrganizations);
            // 用户拥有角色
            Example upmsUserRoleExample = UpmsUserRoleSQL.of().andUserIdEqualTo(upmsUser.getUserId()).example();
            List<UpmsUserRole> upmsUserRoles = Lambkit.get(UpmsUserRoleService.class).dao().find(upmsUserRoleExample);
            data.set("userRoles", upmsUserRoles);
            data.set("sessionId", sessionIdOrtoken);
            data.set("userCode", authUser.getUserCode());
            result = AjaxResult.success().message(username).data(data);
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        } else {
            result = AjaxResult.success().message(username).data(sessionIdOrtoken);
            // 记录用户登录log
            Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
            return result;
        }
    }

    @Override
    public LambkitResult logout(IRequest request) {
        String sessionId = getSessionIdOrToken(request);
        String username = getLoginService(request).authenticate(sessionId);
        getLoginService(request).logout(username);
        request.getSession(false).invalidate();
        // 跳回原地址
        String redirectUrl = request.getHeader("Referer");
        LambkitResult result = AjaxResult.success().data(redirectUrl);
        // 记录用户log
        Lambkit.get(UpmsLogService.class).addLogoutLog(username, result, request);
        return result;
    }

    public LambkitResult loginValidate(IRequest request, UpmsLoginUserToken userToken, String sessionId) {
        String username = userToken.getUsername();
        String password = userToken.getPassword();
        int loginType = userToken.getLoginType();
        if(loginType==1) {
            //手机验证码
            if(StrUtil.isBlank(password)) {
                LambkitResult result = AjaxResult.by(ResultConsts.EMPTY_CAPTCHA).message("验证码不能为空！");
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            }
        } else {
            if (StrUtil.isBlank(password)) {
                LambkitResult result = AjaxResult.by(ResultConsts.EMPTY_PASSWORD).message("密码不能为空！");
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            }
            password = RSAKeyRender.getPassword(request, password);
            if (StrUtil.isBlank(password)) {
                LambkitResult result = AjaxResult.by(ResultConsts.EMPTY_PASSWORD).message("帐号或密码错误！错误6次后锁定!");
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            }
            userToken.setPassword(password);
            String captcha = request.getParameter("captcha");
            if (StrUtil.isBlank(captcha)) {
                LambkitResult result = AjaxResult.by(ResultConsts.EMPTY_CAPTCHA).message("验证码不能为空！");
                // 记录用户登录log
                Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                return result;
            }
            if (!validateCaptcha(request,"captcha")) {
                // 判断请求认证系统是否注册
                Example upmsSystemExample = UpmsSystemSQL.of()
                        .andNameEqualTo(captcha).example();
                Long count = Lambkit.get(UpmsSystemService.class).dao().count(upmsSystemExample);
                if (count==null || 0 == count) {
                    LambkitResult result = AjaxResult.by(ResultConsts.INVALID_CAPTCHA).message("验证码不正确！");
                    // 记录用户登录log
                    Lambkit.get(UpmsLogService.class).addLoginLog(username, result, request);
                    return result;
                }
            }
        }
        return null;
    }

    public boolean validateCaptcha(IRequest request, String paramName) {
        HutoolShearCaptcha captcha = new HutoolShearCaptcha();
        return captcha.validate(request, paramName);
    }
}
